//: typeinfo/NullRobot.java
// Using a dynamic proxy to create a Null Object.
package typeinfo;

import java.lang.reflect.*;
import java.util.*;
import net.mindview.util.*;

class NullRobotProxyHandler implements InvocationHandler
{
    private String nullName;
    
    private Robot proxied = new NRobot();
    
    NullRobotProxyHandler(Class<? extends Robot> type)
    {
        nullName = type.getSimpleName() + " NullRobot";
    }
    
    private class NRobot implements Null, Robot
    {
        public String name()
        {
            return nullName;
        }
        
        public String model()
        {
            return nullName;
        }
        
        public List<Operation> operations()
        {
            return Collections.emptyList();
        }
    }
    
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable
    {
        return method.invoke(proxied, args);
    }
}

public class NullRobot
{
    public static Robot newNullRobot(Class<? extends Robot> type)
    {
        return (Robot)Proxy.newProxyInstance(NullRobot.class.getClassLoader(),
            new Class[] {Null.class, Robot.class},
            new NullRobotProxyHandler(type));
    }
    
    public static void main(String[] args)
    {
        Robot[] bots = {new SnowRemovalRobot("SnowBee"), newNullRobot(SnowRemovalRobot.class)};
        for (Robot bot : bots)
            Robot.Test.test(bot);
    }
} /*
   * Output: Robot name: SnowBee Robot model: SnowBot Series 11 SnowBee can shovel snow SnowBee shoveling snow SnowBee
   * can chip ice SnowBee chipping ice SnowBee can clear the roof SnowBee clearing roof [Null Robot] Robot name:
   * SnowRemovalRobot NullRobot Robot model: SnowRemovalRobot NullRobot
   */// :~
